package bll

import (
	"encoding/json"
	"fmt"
	"net/http"

	"jgt-wallet/src/gopay/alipay"
	payUtil "jgt-wallet/src/gopay/util"
	"jgt-wallet/src/model"
	"jgt-wallet/src/schema"
	"jgt-wallet/src/util"
)

// 支付宝APP
type AlipayApp struct {
	OrderBll       *Order           `inject:""`
	AlipayAppModel model.IAlipayApp `inject:"IAlipayApp"`
}

// Pay 支付
func (a *AlipayApp) Pay(key string, params *schema.AliAppParams) (map[string]string, error) {
	var (
		client *alipay.AppClient
		old    *schema.OrderQueryResult
		order  = new(schema.Order)
		charge = new(alipay.Charge)
		err    error
		fdata  map[string]string
	)

	//检验订单可支付性
	old, err = a.OrderBll.GetOrderResult(params.OrderID)
	if err != nil {
		return nil, err
	}
	if old.Result == schema.RESULT_SUCCESS {
		return nil, fmt.Errorf("订单已支付")
	} else if old.Result == schema.RESULT_ERROR {
		return nil, fmt.Errorf("订单异常,请联系客服")
	}

	order.PayType = schema.PAY_TYPE_ALIPAY_APP
	order.Client = key

	order.RecordID = util.GenerateRecordID()
	order.OrderID = params.OrderID
	order.Price = params.Price
	order.Des = params.Describe
	order.Tag = params.Tag

	client = alipay.GetAppClient(key)
	if client == nil {
		return nil, fmt.Errorf("未找到指定支付宝APP客户端")
	}

	//支付
	charge.MoneyFee = params.Price    //支付额(分)
	charge.Describe = params.Describe //支付描述
	charge.TradeNum = order.RecordID  //交易号
	charge.CallbackURL = params.Url   //回调地址

	fdata, err = client.Pay(charge)
	if err != nil {
		return nil, err
	}

	order.PayData = fdata["orderString"]
	err = a.OrderBll.CreateOrder(order)
	if err != nil {
		return nil, err
	}

	return fdata, nil
}

// Check 同步回调
func (a *AlipayApp) Check(key string, param *schema.AliAppCheckParams) (*schema.AliAppCheckResult, error) {
	var (
		client *alipay.AppClient
		err    error
		data   *alipay.AliAppPayResp
		result = new(schema.AliAppCheckResult)
		order  *schema.Order
	)

	client = alipay.GetAppClient(key)
	if client == nil {
		return nil, fmt.Errorf("未找到指定支付宝APP客户端")
	}
	data, err = client.CheckResult([]byte(param.Result))
	if err != nil {
		return nil, err
	}

	order, err = a.OrderBll.GetOrder(data.OutTradeNo)
	if err != nil {
		return nil, err
	}
	if order == nil {
		return nil, fmt.Errorf("交易订单不存在")
	}

	if data.Code == "10000" {
		result.Result = schema.RESULT_SUCCESS
		result.OrderID, err = a.OrderBll.CheckOrder(data.OutTradeNo, param.Result, schema.CHECK_STATUS_SUCCESS)
	} else if data.Code == "" {
		result.Result = schema.RESULT_ERROR
		result.OrderID, err = a.OrderBll.CheckOrder(data.OutTradeNo, param.Result, schema.CHECK_STATUS_ERROR)
	} else {
		result.Result = schema.RESULT_FAIL
		result.OrderID, err = a.OrderBll.CheckOrder(data.OutTradeNo, param.Result, schema.CHECK_STATUS_FAIL)
	}
	if err != nil {
		return nil, err
	}
	result.RecordID = data.OutTradeNo
	result.OrderID = order.OrderID
	result.Code = data.Code
	result.Price = payUtil.ParseMoneyYuan(data.TotalAmount)
	result.Msg = data.Msg
	result.SubCode = data.SubCode
	result.SubMsg = data.SubMsg

	return result, err
}

// CallBack 异步回调
func (a *AlipayApp) CallBack(key string, w http.ResponseWriter, r *http.Request) error {
	var (
		order  *schema.Order
		data   *alipay.AliWebPayResult
		client *alipay.AppClient
		err    error
	)

	client = alipay.GetAppClient(key)
	if client == nil {
		w.Write([]byte("error"))
		return fmt.Errorf("未找到指定支付宝APP客户端")
	}

	data, err = client.CallBack(w, r)
	if err == nil {
		order, err = a.OrderBll.GetOrder(data.OutTradeNo)
		if err != nil {
			return err
		}

		if data.TradeStatus == schema.RESULT_SUCCESS &&
			payUtil.ParseMoneyYuan(data.TotalAmount) == order.Price {

			a.OrderBll.CallbackOrder(data.OutTradeNo, data.TradeNo, fmt.Sprint(data),
				schema.CALLBACK_STATUS_SUCCESS, payUtil.ParseMoneyYuan(data.ReceiptAmount))

		} else if data.TradeStatus == schema.RESULT_FAIL {

			a.OrderBll.CallbackOrder(data.OutTradeNo, data.TradeNo, fmt.Sprint(data),
				schema.CALLBACK_STATUS_FAIL, payUtil.ParseMoneyYuan(data.ReceiptAmount))

		} else {

			a.OrderBll.CallbackOrder(data.OutTradeNo, data.TradeNo, fmt.Sprint(data),
				schema.CALLBACK_STATUS_ERROR, payUtil.ParseMoneyYuan(data.ReceiptAmount))

		}
	}
	return err
}

// QueryOrderResult 查询订单支付结果
func (a *AlipayApp) QueryOrderResult(recordId string) error {
	var (
		data   *alipay.AliWebAppQueryResult
		client *alipay.AppClient
		order  *schema.Order
		item   = new(schema.Order)
		bs     []byte
		err    error
	)

	order, err = a.OrderBll.GetOrder(recordId)
	if err != nil {
		return err
	}
	if order.PayType != schema.PAY_TYPE_ALIPAY_APP {
		return fmt.Errorf("支付方式错误")
	}
	client = alipay.GetAppClient(order.Client)
	if client == nil {
		return fmt.Errorf("找不到指定客户端")
	}
	item.RecordID = order.RecordID

	data, err = client.QueryOrder(recordId)
	bs, _ = json.Marshal(data)
	if err != nil {
		item.QueryData = err.Error()
	} else {
		item.QueryData = string(bs)
		item.TradeID = data.AlipayTradeQueryResponse.TradeNo
		if data.AlipayTradeQueryResponse.TradeStatus == alipay.TRADE_SUCCESS ||
			data.AlipayTradeQueryResponse.TradeStatus == alipay.TRADE_FINISHED {
			item.Status = schema.ORDER_STATUS_SUCCESS
			item.RealPrice = payUtil.ParseMoneyYuan(data.AlipayTradeQueryResponse.ReceiptAmount)

		} else if data.AlipayTradeQueryResponse.TradeStatus == alipay.TRADE_CLOSED {
			item.Status = schema.ORDER_STATUS_FAIL
		} else {
			item.Status = schema.ORDER_STATUS_ERROR

		}
	}

	return a.OrderBll.UpdateOrder(item)
}
